﻿using System;
using System.Collections;
using System.Collections.Generic;

namespace Poly2Tri
{
	// Token: 0x020003F4 RID: 1012
	public class Contour : Point2DList, ITriangulatable, IEnumerable<TriangulationPoint>, IList<TriangulationPoint>, IEnumerable, ICollection<TriangulationPoint>
	{
		// Token: 0x06001BB1 RID: 7089 RVA: 0x000AECE9 File Offset: 0x000ACEE9
		public Contour(ITriangulatable parent)
		{
			this.mParent = parent;
		}

		// Token: 0x06001BB2 RID: 7090 RVA: 0x000AED0E File Offset: 0x000ACF0E
		public Contour(ITriangulatable parent, IList<TriangulationPoint> points, Point2DList.WindingOrderType windingOrder)
		{
			this.mParent = parent;
			this.AddRange(points, windingOrder);
		}

		// Token: 0x170003DA RID: 986
		public TriangulationPoint this[int index]
		{
			get
			{
				return this.mPoints[index] as TriangulationPoint;
			}
			set
			{
				this.mPoints[index] = value;
			}
		}

		// Token: 0x170003DB RID: 987
		// (get) Token: 0x06001BB5 RID: 7093 RVA: 0x000AED5D File Offset: 0x000ACF5D
		// (set) Token: 0x06001BB6 RID: 7094 RVA: 0x000AED65 File Offset: 0x000ACF65
		public string Name
		{
			get
			{
				return this.mName;
			}
			set
			{
				this.mName = value;
			}
		}

		// Token: 0x170003DC RID: 988
		// (get) Token: 0x06001BB7 RID: 7095 RVA: 0x000AED6E File Offset: 0x000ACF6E
		// (set) Token: 0x06001BB8 RID: 7096 RVA: 0x00002973 File Offset: 0x00000B73
		public IList<DelaunayTriangle> Triangles
		{
			get
			{
				throw new NotImplementedException("PolyHole.Triangles should never get called");
			}
			private set
			{
			}
		}

		// Token: 0x170003DD RID: 989
		// (get) Token: 0x06001BB9 RID: 7097 RVA: 0x000AED7A File Offset: 0x000ACF7A
		public TriangulationMode TriangulationMode
		{
			get
			{
				return this.mParent.TriangulationMode;
			}
		}

		// Token: 0x170003DE RID: 990
		// (get) Token: 0x06001BBA RID: 7098 RVA: 0x000AED87 File Offset: 0x000ACF87
		// (set) Token: 0x06001BBB RID: 7099 RVA: 0x00002973 File Offset: 0x00000B73
		public string FileName
		{
			get
			{
				return this.mParent.FileName;
			}
			set
			{
			}
		}

		// Token: 0x170003DF RID: 991
		// (get) Token: 0x06001BBC RID: 7100 RVA: 0x000AED94 File Offset: 0x000ACF94
		// (set) Token: 0x06001BBD RID: 7101 RVA: 0x00002973 File Offset: 0x00000B73
		public bool DisplayFlipX
		{
			get
			{
				return this.mParent.DisplayFlipX;
			}
			set
			{
			}
		}

		// Token: 0x170003E0 RID: 992
		// (get) Token: 0x06001BBE RID: 7102 RVA: 0x000AEDA1 File Offset: 0x000ACFA1
		// (set) Token: 0x06001BBF RID: 7103 RVA: 0x00002973 File Offset: 0x00000B73
		public bool DisplayFlipY
		{
			get
			{
				return this.mParent.DisplayFlipY;
			}
			set
			{
			}
		}

		// Token: 0x170003E1 RID: 993
		// (get) Token: 0x06001BC0 RID: 7104 RVA: 0x000AEDAE File Offset: 0x000ACFAE
		// (set) Token: 0x06001BC1 RID: 7105 RVA: 0x00002973 File Offset: 0x00000B73
		public float DisplayRotate
		{
			get
			{
				return this.mParent.DisplayRotate;
			}
			set
			{
			}
		}

		// Token: 0x170003E2 RID: 994
		// (get) Token: 0x06001BC2 RID: 7106 RVA: 0x000AEDBB File Offset: 0x000ACFBB
		// (set) Token: 0x06001BC3 RID: 7107 RVA: 0x00002973 File Offset: 0x00000B73
		public double Precision
		{
			get
			{
				return this.mParent.Precision;
			}
			set
			{
			}
		}

		// Token: 0x170003E3 RID: 995
		// (get) Token: 0x06001BC4 RID: 7108 RVA: 0x000AEDC8 File Offset: 0x000ACFC8
		public double MinX
		{
			get
			{
				return this.mBoundingBox.MinX;
			}
		}

		// Token: 0x170003E4 RID: 996
		// (get) Token: 0x06001BC5 RID: 7109 RVA: 0x000AEDD5 File Offset: 0x000ACFD5
		public double MaxX
		{
			get
			{
				return this.mBoundingBox.MaxX;
			}
		}

		// Token: 0x170003E5 RID: 997
		// (get) Token: 0x06001BC6 RID: 7110 RVA: 0x000AEDE2 File Offset: 0x000ACFE2
		public double MinY
		{
			get
			{
				return this.mBoundingBox.MinY;
			}
		}

		// Token: 0x170003E6 RID: 998
		// (get) Token: 0x06001BC7 RID: 7111 RVA: 0x000AEDEF File Offset: 0x000ACFEF
		public double MaxY
		{
			get
			{
				return this.mBoundingBox.MaxY;
			}
		}

		// Token: 0x170003E7 RID: 999
		// (get) Token: 0x06001BC8 RID: 7112 RVA: 0x000AEDFC File Offset: 0x000ACFFC
		public Rect2D Bounds
		{
			get
			{
				return this.mBoundingBox;
			}
		}

		// Token: 0x06001BC9 RID: 7113 RVA: 0x000AEE04 File Offset: 0x000AD004
		public override string ToString()
		{
			return this.mName + " : " + base.ToString();
		}

		// Token: 0x06001BCA RID: 7114 RVA: 0x000AEE1C File Offset: 0x000AD01C
		IEnumerator<TriangulationPoint> IEnumerable<TriangulationPoint>.GetEnumerator()
		{
			return new TriangulationPointEnumerator(this.mPoints);
		}

		// Token: 0x06001BCB RID: 7115 RVA: 0x000AEE29 File Offset: 0x000AD029
		public int IndexOf(TriangulationPoint p)
		{
			return this.mPoints.IndexOf(p);
		}

		// Token: 0x06001BCC RID: 7116 RVA: 0x000AEE37 File Offset: 0x000AD037
		public void Add(TriangulationPoint p)
		{
			this.Add(p, -1, true);
		}

		// Token: 0x06001BCD RID: 7117 RVA: 0x000AEE44 File Offset: 0x000AD044
		protected override void Add(Point2D p, int idx, bool bCalcWindingOrderAndEpsilon)
		{
			TriangulationPoint triangulationPoint;
			if (p is TriangulationPoint)
			{
				triangulationPoint = (p as TriangulationPoint);
			}
			else
			{
				triangulationPoint = new TriangulationPoint(p.X, p.Y);
			}
			if (idx < 0)
			{
				this.mPoints.Add(triangulationPoint);
			}
			else
			{
				this.mPoints.Insert(idx, triangulationPoint);
			}
			this.mBoundingBox.AddPoint(triangulationPoint);
			if (bCalcWindingOrderAndEpsilon)
			{
				if (this.mWindingOrder == Point2DList.WindingOrderType.Unknown)
				{
					this.mWindingOrder = base.CalculateWindingOrder();
				}
				this.mEpsilon = base.CalculateEpsilon();
			}
		}

		// Token: 0x06001BCE RID: 7118 RVA: 0x000AEED8 File Offset: 0x000AD0D8
		public override void AddRange(IEnumerator<Point2D> iter, Point2DList.WindingOrderType windingOrder)
		{
			if (iter == null)
			{
				return;
			}
			if (this.mWindingOrder == Point2DList.WindingOrderType.Unknown && base.Count == 0)
			{
				this.mWindingOrder = windingOrder;
			}
			bool flag = base.WindingOrder != Point2DList.WindingOrderType.Unknown && windingOrder != Point2DList.WindingOrderType.Unknown && base.WindingOrder != windingOrder;
			bool flag2 = true;
			int count = this.mPoints.Count;
			iter.Reset();
			while (iter.MoveNext())
			{
				TriangulationPoint item;
				if (iter.Current is TriangulationPoint)
				{
					item = (iter.Current as TriangulationPoint);
				}
				else
				{
					item = new TriangulationPoint(iter.Current.X, iter.Current.Y);
				}
				if (!flag2)
				{
					flag2 = true;
					this.mPoints.Add(item);
				}
				else if (flag)
				{
					this.mPoints.Insert(count, item);
				}
				else
				{
					this.mPoints.Add(item);
				}
				this.mBoundingBox.AddPoint(iter.Current);
			}
			if (this.mWindingOrder == Point2DList.WindingOrderType.Unknown && windingOrder == Point2DList.WindingOrderType.Unknown)
			{
				this.mWindingOrder = base.CalculateWindingOrder();
			}
			this.mEpsilon = base.CalculateEpsilon();
		}

		// Token: 0x06001BCF RID: 7119 RVA: 0x000AF00C File Offset: 0x000AD20C
		public void AddRange(IList<TriangulationPoint> points, Point2DList.WindingOrderType windingOrder)
		{
			if (points == null || points.Count < 1)
			{
				return;
			}
			if (this.mWindingOrder == Point2DList.WindingOrderType.Unknown && base.Count == 0)
			{
				this.mWindingOrder = windingOrder;
			}
			int count = points.Count;
			bool flag = base.WindingOrder != Point2DList.WindingOrderType.Unknown && windingOrder != Point2DList.WindingOrderType.Unknown && base.WindingOrder != windingOrder;
			for (int i = 0; i < count; i++)
			{
				int index = i;
				if (flag)
				{
					index = points.Count - i - 1;
				}
				this.Add(points[index], -1, false);
			}
			if (this.mWindingOrder == Point2DList.WindingOrderType.Unknown)
			{
				this.mWindingOrder = base.CalculateWindingOrder();
			}
			this.mEpsilon = base.CalculateEpsilon();
		}

		// Token: 0x06001BD0 RID: 7120 RVA: 0x000AF0CC File Offset: 0x000AD2CC
		public void Insert(int idx, TriangulationPoint p)
		{
			this.Add(p, idx, true);
		}

		// Token: 0x06001BD1 RID: 7121 RVA: 0x000AF0D7 File Offset: 0x000AD2D7
		public bool Remove(TriangulationPoint p)
		{
			return this.Remove(p);
		}

		// Token: 0x06001BD2 RID: 7122 RVA: 0x000AF0E0 File Offset: 0x000AD2E0
		public bool Contains(TriangulationPoint p)
		{
			return this.mPoints.Contains(p);
		}

		// Token: 0x06001BD3 RID: 7123 RVA: 0x000AF0F0 File Offset: 0x000AD2F0
		public void CopyTo(TriangulationPoint[] array, int arrayIndex)
		{
			int num = Math.Min(base.Count, array.Length - arrayIndex);
			for (int i = 0; i < num; i++)
			{
				array[arrayIndex + i] = (this.mPoints[i] as TriangulationPoint);
			}
		}

		// Token: 0x06001BD4 RID: 7124 RVA: 0x000AF136 File Offset: 0x000AD336
		protected void AddHole(Contour c)
		{
			c.mParent = this;
			this.mHoles.Add(c);
		}

		// Token: 0x06001BD5 RID: 7125 RVA: 0x000AF14C File Offset: 0x000AD34C
		public int GetNumHoles(bool parentIsHole)
		{
			int num = (!parentIsHole) ? 1 : 0;
			foreach (Contour contour in this.mHoles)
			{
				num += contour.GetNumHoles(!parentIsHole);
			}
			return num;
		}

		// Token: 0x06001BD6 RID: 7126 RVA: 0x000AF1C0 File Offset: 0x000AD3C0
		public int GetNumHoles()
		{
			return this.mHoles.Count;
		}

		// Token: 0x06001BD7 RID: 7127 RVA: 0x000AF1CD File Offset: 0x000AD3CD
		public Contour GetHole(int idx)
		{
			if (idx < 0 || idx >= this.mHoles.Count)
			{
				return null;
			}
			return this.mHoles[idx];
		}

		// Token: 0x06001BD8 RID: 7128 RVA: 0x000AF1F8 File Offset: 0x000AD3F8
		public void GetActualHoles(bool parentIsHole, ref List<Contour> holes)
		{
			if (parentIsHole)
			{
				holes.Add(this);
			}
			foreach (Contour contour in this.mHoles)
			{
				contour.GetActualHoles(!parentIsHole, ref holes);
			}
		}

		// Token: 0x06001BD9 RID: 7129 RVA: 0x000AF268 File Offset: 0x000AD468
		public List<Contour>.Enumerator GetHoleEnumerator()
		{
			return this.mHoles.GetEnumerator();
		}

		// Token: 0x06001BDA RID: 7130 RVA: 0x000AF278 File Offset: 0x000AD478
		public void InitializeHoles(ConstrainedPointSet cps)
		{
			Contour.InitializeHoles(this.mHoles, this, cps);
			foreach (Contour contour in this.mHoles)
			{
				contour.InitializeHoles(cps);
			}
		}

		// Token: 0x06001BDB RID: 7131 RVA: 0x000AF2E4 File Offset: 0x000AD4E4
		public static void InitializeHoles(List<Contour> holes, ITriangulatable parent, ConstrainedPointSet cps)
		{
			int num = holes.Count;
			int i;
			for (i = 0; i < num; i++)
			{
				int j = i + 1;
				while (j < num)
				{
					bool flag = PolygonUtil.PolygonsAreSame2D(holes[i], holes[j]);
					if (flag)
					{
						holes.RemoveAt(j);
						num--;
					}
					else
					{
						j++;
					}
				}
			}
			i = 0;
			while (i < num)
			{
				bool flag2 = true;
				int k = i + 1;
				while (k < num)
				{
					if (PolygonUtil.PolygonContainsPolygon(holes[i], holes[i].Bounds, holes[k], holes[k].Bounds, false))
					{
						holes[i].AddHole(holes[k]);
						holes.RemoveAt(k);
						num--;
					}
					else
					{
						if (PolygonUtil.PolygonContainsPolygon(holes[k], holes[k].Bounds, holes[i], holes[i].Bounds, false))
						{
							holes[k].AddHole(holes[i]);
							holes.RemoveAt(i);
							num--;
							flag2 = false;
							break;
						}
						bool flag3 = PolygonUtil.PolygonsIntersect2D(holes[i], holes[i].Bounds, holes[k], holes[k].Bounds);
						if (flag3)
						{
							PolygonOperationContext polygonOperationContext = new PolygonOperationContext();
							if (!polygonOperationContext.Init(PolygonUtil.PolyOperation.Union | PolygonUtil.PolyOperation.Intersect, holes[i], holes[k]))
							{
								if (polygonOperationContext.mError == PolygonUtil.PolyUnionError.Poly1InsidePoly2)
								{
									holes[k].AddHole(holes[i]);
									holes.RemoveAt(i);
									num--;
									flag2 = false;
									break;
								}
								throw new Exception("PolygonOperationContext.Init had an error during initialization");
							}
							else
							{
								if (PolygonUtil.PolygonOperation(polygonOperationContext) != PolygonUtil.PolyUnionError.None)
								{
									throw new Exception("PolygonOperation had an error!");
								}
								Point2DList union = polygonOperationContext.Union;
								Point2DList intersect = polygonOperationContext.Intersect;
								Contour contour = new Contour(parent);
								contour.AddRange(union);
								contour.Name = string.Concat(new string[]
								{
									"(",
									holes[i].Name,
									" UNION ",
									holes[k].Name,
									")"
								});
								contour.WindingOrder = Point2DList.WindingOrderType.CCW;
								int numHoles = holes[i].GetNumHoles();
								for (int l = 0; l < numHoles; l++)
								{
									contour.AddHole(holes[i].GetHole(l));
								}
								numHoles = holes[k].GetNumHoles();
								for (int m = 0; m < numHoles; m++)
								{
									contour.AddHole(holes[k].GetHole(m));
								}
								Contour contour2 = new Contour(contour);
								contour2.AddRange(intersect);
								contour2.Name = string.Concat(new string[]
								{
									"(",
									holes[i].Name,
									" INTERSECT ",
									holes[k].Name,
									")"
								});
								contour2.WindingOrder = Point2DList.WindingOrderType.CCW;
								contour.AddHole(contour2);
								holes[i] = contour;
								holes.RemoveAt(k);
								num--;
								k = i + 1;
							}
						}
						else
						{
							k++;
						}
					}
				}
				if (flag2)
				{
					i++;
				}
			}
			num = holes.Count;
			for (i = 0; i < num; i++)
			{
				int count = holes[i].Count;
				for (int n = 0; n < count; n++)
				{
					int index = holes[i].NextIndex(n);
					uint constraintCode = TriangulationConstraint.CalculateContraintCode(holes[i][n], holes[i][index]);
					TriangulationConstraint triangulationConstraint = null;
					if (!cps.TryGetConstraint(constraintCode, out triangulationConstraint))
					{
						triangulationConstraint = new TriangulationConstraint(holes[i][n], holes[i][index]);
						cps.AddConstraint(triangulationConstraint);
					}
					if (holes[i][n].VertexCode == triangulationConstraint.P.VertexCode)
					{
						holes[i][n] = triangulationConstraint.P;
					}
					else if (holes[i][index].VertexCode == triangulationConstraint.P.VertexCode)
					{
						holes[i][index] = triangulationConstraint.P;
					}
					if (holes[i][n].VertexCode == triangulationConstraint.Q.VertexCode)
					{
						holes[i][n] = triangulationConstraint.Q;
					}
					else if (holes[i][index].VertexCode == triangulationConstraint.Q.VertexCode)
					{
						holes[i][index] = triangulationConstraint.Q;
					}
				}
			}
		}

		// Token: 0x06001BDC RID: 7132 RVA: 0x000AF7F8 File Offset: 0x000AD9F8
		public void Prepare(TriangulationContext tcx)
		{
			throw new NotImplementedException("PolyHole.Prepare should never get called");
		}

		// Token: 0x06001BDD RID: 7133 RVA: 0x000AF804 File Offset: 0x000ADA04
		public void AddTriangle(DelaunayTriangle t)
		{
			throw new NotImplementedException("PolyHole.AddTriangle should never get called");
		}

		// Token: 0x06001BDE RID: 7134 RVA: 0x000AF810 File Offset: 0x000ADA10
		public void AddTriangles(IEnumerable<DelaunayTriangle> list)
		{
			throw new NotImplementedException("PolyHole.AddTriangles should never get called");
		}

		// Token: 0x06001BDF RID: 7135 RVA: 0x000AF81C File Offset: 0x000ADA1C
		public void ClearTriangles()
		{
			throw new NotImplementedException("PolyHole.ClearTriangles should never get called");
		}

		// Token: 0x06001BE0 RID: 7136 RVA: 0x000AF828 File Offset: 0x000ADA28
		public Point2D FindPointInContour()
		{
			if (base.Count < 3)
			{
				return null;
			}
			Point2D centroid = base.GetCentroid();
			if (this.IsPointInsideContour(centroid))
			{
				return centroid;
			}
			Random random = new Random();
			do
			{
				centroid.X = random.NextDouble() * (this.MaxX - this.MinX) + this.MinX;
				centroid.Y = random.NextDouble() * (this.MaxY - this.MinY) + this.MinY;
			}
			while (!this.IsPointInsideContour(centroid));
			return centroid;
		}

		// Token: 0x06001BE1 RID: 7137 RVA: 0x000AF8B4 File Offset: 0x000ADAB4
		public bool IsPointInsideContour(Point2D p)
		{
			if (PolygonUtil.PointInPolygon2D(this, p))
			{
				foreach (Contour contour in this.mHoles)
				{
					if (contour.IsPointInsideContour(p))
					{
						return false;
					}
				}
				return true;
			}
			return false;
		}

		// Token: 0x04001D64 RID: 7524
		private List<Contour> mHoles = new List<Contour>();

		// Token: 0x04001D65 RID: 7525
		private ITriangulatable mParent;

		// Token: 0x04001D66 RID: 7526
		private string mName = string.Empty;
	}
}
